package cn.org.donald.sensitive;

import cn.org.donald.sensitive.model.FactoryEnum;
import cn.org.donald.sensitive.model.FindStringRegex;
import cn.org.donald.sensitive.model.PdfMatchItem;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfTextLocation;
import com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Donald
 * @since 2023-11-14 11:55:50
 **/
public class NewTest {
    public static void main(String[] args) throws IOException {
        String src = "D:\\develop\\sensitive\\1.pdf";
        String desc = "D:\\develop\\sensitive\\1-new.pdf";
        List<String> list = new ArrayList<>();
        list.add(FindStringRegex.MOBILE_PHONE);
        Path filePath = Paths.get(src);
        List<String> sensitiveString = FactoryEnum.getInstance(filePath).getSensitiveString(list);

        Map<Integer, List<PdfMatchItem>> textPosition = getTextPosition(src, desc, sensitiveString.stream().collect(Collectors.toMap(s -> s, s -> {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
                sb.append("*");
            }
            return sb.toString();
        })));
        PdfFont font = PdfFontFactory.createFont("./data/SIMSUN.TTF", PdfEncodings.IDENTITY_H);
        overText(src, desc, textPosition, font);
    }


    private static Map<Integer, List<PdfMatchItem>> getTextPosition(String src, String dest, Map<String, String> replaceList) throws IOException {

        PdfReader reader = new PdfReader(src);
        PdfDocument pdfDocument = new PdfDocument(reader, new PdfWriter(dest));
        Map<Integer, List<PdfMatchItem>> result = new HashMap<>();
        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {


            List<PdfMatchItem> pdfMatchItems = new ArrayList<>();
            int finalI = i;
            replaceList.forEach((k, v) -> {
                PdfPage page = pdfDocument.getPage(finalI);
                RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy("\\" + k);
                PdfCanvasProcessor canvasProcessor = new PdfCanvasProcessor(strategy);
                canvasProcessor.processPageContent(page);
                Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
                PdfCanvas pdfCanvas = new PdfCanvas(page);
                pdfCanvas.setLineWidth(0.5f);

                for (IPdfTextLocation location : resultantLocations) {
                    Rectangle rectangle = location.getRectangle();
                    pdfCanvas.rectangle(rectangle);
                    pdfCanvas.setStrokeColor(ColorConstants.RED);
                    pdfCanvas.stroke();

                    PdfMatchItem pdfMatchItem = new PdfMatchItem();
                    pdfMatchItem.setCurrentPage(location.getPageNumber());
                    pdfMatchItem.setX(rectangle.getX());
                    pdfMatchItem.setY(rectangle.getY());
                    pdfMatchItem.setPageWidth(rectangle.getWidth());
                    pdfMatchItem.setPageHeight(rectangle.getHeight());
                    pdfMatchItem.setKey(k);
                    pdfMatchItem.setValue(v);
                    pdfMatchItems.add(pdfMatchItem);
                }
            });
            result.put(i, pdfMatchItems);
        }
        pdfDocument.close();
        return result;
    }

    /**
     * 覆盖原有的内容 并填充新内容
     *
     * @param sourcePath 源文件
     * @param finishPath 替换后的文件
     */
    private static void overText(String sourcePath, String finishPath, Map<Integer, List<PdfMatchItem>> map, PdfFont font) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourcePath), new PdfWriter(finishPath));
        //pdfDoc.getFirstPage().newContentStreamAfter() 会覆盖掉字体
        //pdfDoc.getFirstPage().newContentStreamBefore() 只会在字体的下层添加一个背景色
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfCanvas canvas = new PdfCanvas(pdfDoc.getPage(i).newContentStreamAfter(),
                    pdfDoc.getPage(i).getResources(), pdfDoc);

            canvas.saveState();
            List<PdfMatchItem> pdfMatchItems = map.get(i);
            //用白色背景覆盖原本的字体
            for (PdfMatchItem pdfMatchItem : pdfMatchItems) {
                canvas.setFillColor(ColorConstants.WHITE);
                //覆盖的时候y + 0.35   填充字体的时候 + 1.5 主要就是避免覆盖占位符下面的线
                canvas.rectangle(pdfMatchItem.getX(), pdfMatchItem.getY() + 0.35, pdfMatchItem.getPageWidth(), pdfMatchItem.getPageHeight());
            }
            canvas.fill();
            canvas.restoreState();

            //填充新内容
            canvas.beginText();
            for (PdfMatchItem pdfMatchItem : pdfMatchItems) {
                canvas.setFontAndSize(font, pdfMatchItem.getPageHeight());
                canvas.setTextMatrix(pdfMatchItem.getX(), pdfMatchItem.getY() + 1.5f);
                canvas.newlineShowText(pdfMatchItem.getValue());
            }
            canvas.endText();
        }

        pdfDoc.close();

    }
}
